//
//
//
//
//
//
// Socks4Server.C

#include "Socks4Server.h"
#include "LogManager.h"
#include "ThreadManager.h"
#include "Socks4Proxy.h"

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/socketvar.h>
#include <netinet/in.h>

Mutex Socks4Server::_instanceMutex;
Socks4Server* Socks4Server::_instance = NULL;

Socks4Server* Socks4Server::Instance(U32 num)
{
	_instanceMutex.Lock();
	if(NULL == _instance)
	{
		_instance = new Socks4Server(num);
	}
	_instanceMutex.UnLock();
	return _instance;
}

void Socks4Server::Destroy(Socks4Server* p)
{
	delete p;
}

Socks4Server::Socks4Server(U32 num)
{
	_poolInstance = ThreadManager::Instance();
	_poolInstance->Initialize(num);
}

Socks4Server::~Socks4Server(){};

void Socks4Server::Svc()
{
	LOGTRACE("Socks4Server::Svc");


	int nRet = 0;

	int listenFD = socket(AF_INET, SOCK_STREAM, 0);
	if(listenFD == -1)
	{
		LOGERROR("Error create listen socket");
		return;
	}
	
	struct sockaddr_in  servaddr;

	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
	servaddr.sin_port = htons (SERVER4PROXY_PORT);

	nRet = bind(listenFD, (struct sockaddr *)&servaddr, sizeof(servaddr));
	if(nRet == -1)
	{
		LOGERROR("Error bind");
		return;
	}

	nRet = listen(listenFD, 5);
	if(nRet == -1)
	{
		LOGERROR("Error listen");
		return;
	}

	while(true)
	{
		nRet = accept(listenFD, NULL, NULL);
		if(nRet == -1)
		{
			LOGERROR("ERROR accept");
			continue;
		}
		BaseJob* p = new Socks4Proxy(0, "--", NULL, nRet);
		_poolInstance->AddJob(p);

	}
}


//
//
// Report
// Report Scoks4Server properties. connections,time...
//
void Socks4Server::Report(std::ostream& os)
{
	LOGTRACE("Socks4Server::Report");
}


void Socks4Server::SignalExit(void)
{
	_poolInstance->SignalExit();
}


void Socks4Server::ForceStop()
{
	LOGTRACE("Socks4Server::ForceStop");
}


//
// first wait activeobject thread,
// then wait thread pool threads
//
void Socks4Server::WaitAll()
{
	ActiveObject::Wait();
	_poolInstance->WaitAll();
}
